Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(eth): protos, go-ethereum, eth types, and evm module types #1837

Merged
merged 8 commits into from
Apr 16, 2024

Conversation

Unique-Divine
Copy link
Member

@Unique-Divine Unique-Divine commented Apr 6, 2024

Purpose / Abstract

Changes

  • Introduced Ethereum transaction, block, and log definitions.
  • Added Ethereum ChainConfig parameters and EVM module settings .
  • Implemented genesis state and account setup for initializing EVM modules.
  • gRPC services for Ethereum data querying (accounts, transactions, gas, etc.).
  • Transaction submission with support for Ethereum transactions and governance operations.
  • Ethereum accounts and transaction indexing data structures.
  • TxOptions

Summary by CodeRabbit

  • New Features

    • Introduced Ethereum transaction, account, and blockchain query functionalities.
    • Added Ethereum transaction submission and governance operations.
    • Enhanced Ethereum key management and cryptographic functions.
    • Improved encoding and decoding capabilities for Ethereum transaction and account data.
    • Implemented Ethereum EIP-712 compliance for transaction handling.
  • Documentation

    • Updated contributing guidelines and issue templates for the project.
    • Established automated workflows for build, lint, security checks, and dependency reviews.
  • Chores

    • Updated copyright information in the LICENSE.md.
    • Configured various GitHub repository management settings and workflows.
  • Refactor

    • Excluded unnecessary files from Docker builds and version control.

@Unique-Divine Unique-Divine requested a review from a team as a code owner April 6, 2024 06:47
Copy link
Contributor

coderabbitai bot commented Apr 6, 2024

Walkthrough

This extensive update brings Ethereum Virtual Machine (EVM) compatibility to the project, introducing new protobuf files for Ethereum transactions, logs, and queries. It also includes enhancements in Ethereum cryptography and type handling, as well as integration of Ethereum's JSON-RPC specifications to support Solidity-based decentralized applications (dApps).

Changes

Files Changes Summary
proto/eth/evm/v1/*.proto New protobuf definitions for EVM, transactions, and queries.
eth/crypto/*, eth/types/* Enhancements in Ethereum cryptography and type handling.
eth/ethereum/eip712/*.go Functions for EIP-712 compliance and Ethereum message handling.
geth/.github/* GitHub workflows and community guidelines enhancements.
geth/.dockerignore, .gitattributes, .gitignore, .golangci.yml Development environment and linting configurations.
LICENSE.md Update in copyright holder and removal of promotional text.

Possibly related issues

  • epic(evm): Nibiru EVM tracking ticket #1836: The objectives in this issue to implement Ethereum protobufs, types, and cryptography additions align directly with the changes in this PR, notably reflected in the proto/eth/evm/v1/*.proto and eth/crypto/* files.

Poem

🐰🎉
In the realm of code, where innovations take flight,
A rabbit weaves changes, bringing Ethereum's light.
With each commit and push, a dance of delight,
EVM's embrace grows, in the glow of bytes bright.
Crafting a future where dApps will soar,
The rabbit codes on, dreaming of more. 🚀🌌
🐰🎉


Recent Review Details

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 182ea3a and a1d11cd.
Files selected for processing (1)
  • CHANGELOG.md (1 hunks)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review Status

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 68f8f5b and 7871ecc.
Files ignored due to path filters (11)
  • eth/types/account.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • eth/types/dynamic_fee.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • eth/types/indexer.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • eth/types/web3.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • x/evm/types/events.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • x/evm/types/evm.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • x/evm/types/genesis.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • x/evm/types/query.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • x/evm/types/query.pb.gw.go is excluded by !**/*.pb.gw.go, !**/*.pb.gw.go
  • x/evm/types/tx.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • x/evm/types/tx.pb.gw.go is excluded by !**/*.pb.gw.go, !**/*.pb.gw.go
Files selected for processing (9)
  • proto/eth/evm/v1/events.proto (1 hunks)
  • proto/eth/evm/v1/evm.proto (1 hunks)
  • proto/eth/evm/v1/genesis.proto (1 hunks)
  • proto/eth/evm/v1/query.proto (1 hunks)
  • proto/eth/evm/v1/tx.proto (1 hunks)
  • proto/eth/types/v1/account.proto (1 hunks)
  • proto/eth/types/v1/dynamic_fee.proto (1 hunks)
  • proto/eth/types/v1/indexer.proto (1 hunks)
  • proto/eth/types/v1/web3.proto (1 hunks)
Additional comments not posted (13)
proto/eth/types/v1/dynamic_fee.proto (1)

1-13: LGTM! The definition of ExtensionOptionDynamicFeeTx correctly specifies the max priority price for Cosmos transactions, aligning with the EIP-1559 specification. The use of cosmossdk.io/math.Int for max_priority_price is appropriate for handling large numbers.

proto/eth/types/v1/account.proto (1)

1-26: LGTM! The EthAccount message is correctly defined to ensure compatibility with Ethereum accounts and the Cosmos SDK. The use of gogoproto options and the embedding of BaseAccount are appropriately applied.

proto/eth/types/v1/web3.proto (1)

1-26: LGTM! The ExtensionOptionsWeb3Tx message is correctly defined to support Web3 transactions, including typed chain ID and fee delegation, aligning with EIP712 specifications.

proto/eth/types/v1/indexer.proto (1)

1-31: LGTM! The TxResult message is well-structured to capture essential details of Ethereum transactions for indexing purposes. The fields chosen are appropriate for tracking transaction processing and gas usage.

proto/eth/evm/v1/genesis.proto (1)

1-28: LGTM! The GenesisState and GenesisAccount messages are correctly defined to represent the initial state for the EVM module, including genesis accounts with their code and storage.

proto/eth/evm/v1/events.proto (1)

1-45: LGTM! The event messages introduced in this file are well-structured to capture essential details of Ethereum transactions, logs, and block blooms, ensuring detailed logging and event representation for the EVM module.

proto/eth/evm/v1/tx.proto (1)

1-178: LGTM! The messages and service defined in this file correctly represent various Ethereum transaction types and provide a structured way to submit transactions and update module parameters for the EVM module.

proto/eth/evm/v1/evm.proto (1)

1-222: LGTM! The messages defined in this file correctly represent various configurations, states, and logs for the EVM module, ensuring a robust and configurable EVM implementation. The TraceConfig message, in particular, provides comprehensive tracing options, which are crucial for debugging and analysis.

proto/eth/evm/v1/query.proto (5)

14-303: Ensure all newly introduced gRPC service methods and message types are thoroughly documented.
Adding comments to explain the purpose and usage of each service method and message type enhances code readability and maintainability. It's especially important for public APIs, as it aids developers in understanding how to interact with the services.


18-18: Verify the REST endpoint paths for consistency and adherence to RESTful design principles.
The REST endpoint paths should be consistent and follow RESTful design principles. For example, using plural nouns (accounts instead of account) and ensuring a logical hierarchy in the paths can improve the API's intuitiveness.


53-66: Consider adding POST methods for EthCall, EstimateGas, and TraceTx services.
The EthCall, EstimateGas, and TraceTx services currently use GET methods, which may not be suitable for operations that involve complex request bodies. Consider changing these to POST methods to support more complex and potentially large request payloads.


219-228: Review the use of bytes type for fields that represent addresses or other hex-encoded strings.
For fields like proposer_address in EthCallRequest, consider using a string type if these addresses are expected to be hex-encoded. This can improve clarity and reduce the need for conversions in client code.


302-302: Ensure the custom type cosmossdk.io/math.Int for base_fee is correctly implemented and tested.
The use of a custom type for base_fee in QueryBaseFeeResponse suggests specialized handling or functionality. Verify that this custom type is correctly implemented, especially regarding serialization and deserialization, and thoroughly tested to handle various scenarios.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review Status

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 7871ecc and a7d7e90.
Files selected for processing (1)
  • CHANGELOG.md (1 hunks)
Additional comments not posted (1)
CHANGELOG.md (1)

63-63: The changelog entry is well-documented and follows the standard format, providing clear information about the new feature related to Ethereum in the Nibiru EVM module.

* feat(eth): unit tests for types, crypto, encoding

## Impl `go-ethereum`

Adds `go-ethereum` fork with an `Interpreter` interface for running smart
contracts in integration tests.

```go
type Interpreter interface {
	// Run loops and evaluates the contract's code with the given input data and returns
	// the return byte-slice and an error if one occurred.
	Run(contract *Contract, input []byte, static bool) ([]byte, error)
}
```

An `Interpreter` is used to run Ethereum based contracts and will utilize the
passed environment to query external sources for state information.
The Interpreter will run the byte code VM based on the passed
configuration.

Changes from go-ethereum v1.11:

* Set `callcode` to use `readOnly` mode for precompiled calls.
* Remove `IsStateful` function from the `PrecompiledContract` interface, as this remains unused.
* Support stateful precompiled contracts.
* Add `Address` function to `PrecompiledContract` interface.
* Implement custom active precompiles for the EVM.
* Define `Interpreter` interface for the EVM.
* Move the `JumpTable` defaults to a separate function.
* Refactor `Stack` implementation
@Unique-Divine Unique-Divine changed the title feat(eth): protos, eth types, and evm module types feat(eth): protos, go-ethereum, eth types, and evm module types Apr 6, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 16

Review Status

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between a7d7e90 and f7a9a66.
Files ignored due to path filters (15)
  • eth/crypto/ethsecp256k1/keys.pb.go is excluded by !**/*.pb.go
  • geth/accounts/usbwallet/trezor/messages-common.pb.go is excluded by !**/*.pb.go
  • geth/accounts/usbwallet/trezor/messages-ethereum.pb.go is excluded by !**/*.pb.go
  • geth/accounts/usbwallet/trezor/messages-management.pb.go is excluded by !**/*.pb.go
  • geth/accounts/usbwallet/trezor/messages.pb.go is excluded by !**/*.pb.go
  • geth/cmd/clef/docs/clef_architecture_pt1.png is excluded by !**/*.png
  • geth/cmd/clef/docs/clef_architecture_pt2.png is excluded by !**/*.png
  • geth/cmd/clef/docs/clef_architecture_pt3.png is excluded by !**/*.png
  • geth/cmd/clef/docs/clef_architecture_pt4.png is excluded by !**/*.png
  • geth/cmd/clef/docs/qubes/clef_qubes_http.png is excluded by !**/*.png
  • geth/cmd/clef/docs/qubes/clef_qubes_qrexec.png is excluded by !**/*.png
  • geth/cmd/clef/docs/qubes/qrexec-example.png is excluded by !**/*.png
  • geth/cmd/clef/docs/qubes/qubes_newaccount-1.png is excluded by !**/*.png
  • geth/cmd/clef/docs/qubes/qubes_newaccount-2.png is excluded by !**/*.png
  • geth/cmd/clef/sign_flow.png is excluded by !**/*.png
Files selected for processing (56)
  • CHANGELOG.md (1 hunks)
  • cmd/ethclient/const.go (1 hunks)
  • eth/crypto/codec/amino.go (1 hunks)
  • eth/crypto/codec/codec.go (1 hunks)
  • eth/crypto/ethsecp256k1/benchmark_test.go (1 hunks)
  • eth/crypto/ethsecp256k1/ethsecp256k1.go (1 hunks)
  • eth/crypto/ethsecp256k1/ethsecp256k1_test.go (1 hunks)
  • eth/crypto/hd/algorithm.go (1 hunks)
  • eth/crypto/hd/algorithm_test.go (1 hunks)
  • eth/crypto/hd/benchmark_test.go (1 hunks)
  • eth/crypto/hd/utils_test.go (1 hunks)
  • eth/crypto/keyring/options.go (1 hunks)
  • eth/crypto/secp256r1/verify.go (1 hunks)
  • eth/encoding/codec/codec.go (1 hunks)
  • eth/encoding/config.go (1 hunks)
  • eth/encoding/config_test.go (1 hunks)
  • eth/ethereum/eip712/domain.go (1 hunks)
  • eth/ethereum/eip712/eip712.go (1 hunks)
  • eth/ethereum/eip712/eip712_fuzzer_test.go (1 hunks)
  • eth/ethereum/eip712/eip712_legacy.go (1 hunks)
  • eth/ethereum/eip712/eip712_test.go (1 hunks)
  • eth/ethereum/eip712/encoding.go (1 hunks)
  • eth/ethereum/eip712/encoding_legacy.go (1 hunks)
  • eth/ethereum/eip712/message.go (1 hunks)
  • eth/ethereum/eip712/preprocess.go (1 hunks)
  • eth/ethereum/eip712/preprocess_test.go (1 hunks)
  • eth/ethereum/eip712/types.go (1 hunks)
  • eth/types/assert.go (1 hunks)
  • eth/types/chain_id.go (1 hunks)
  • eth/types/chain_id_test.go (1 hunks)
  • eth/types/codec.go (1 hunks)
  • eth/types/errors.go (1 hunks)
  • eth/types/hdpath.go (1 hunks)
  • eth/types/safe_math.go (1 hunks)
  • geth/.dockerignore (1 hunks)
  • geth/.gitattributes (1 hunks)
  • geth/.github/CODEOWNERS (1 hunks)
  • geth/.github/CONTRIBUTING.md (1 hunks)
  • geth/.github/ISSUE_TEMPLATE/bug.md (1 hunks)
  • geth/.github/ISSUE_TEMPLATE/feature.md (1 hunks)
  • geth/.github/ISSUE_TEMPLATE/question.md (1 hunks)
  • geth/.github/no-response.yml (1 hunks)
  • geth/.github/stale.yml (1 hunks)
  • geth/.github/workflows/build.yml (1 hunks)
  • geth/.github/workflows/dependencies.yml (1 hunks)
  • geth/.github/workflows/lint.yml (1 hunks)
  • geth/.github/workflows/markdown-links.yml (1 hunks)
  • geth/.github/workflows/security.yml (1 hunks)
  • geth/.github/workflows/super-linter.yml (1 hunks)
  • geth/.github/workflows/test.yml (1 hunks)
  • geth/.gitignore (1 hunks)
  • geth/.gitmodules (1 hunks)
  • geth/.golangci.yml (1 hunks)
  • geth/.mailmap (1 hunks)
  • geth/.markdownlint.yml (1 hunks)
  • geth/.markdownlintignore (1 hunks)
Files not processed due to max files limit (39)
  • geth/.protolint.yml
  • geth/.travis.yml
  • geth/.yamllint
  • geth/AUTHORS
  • geth/COPYING
  • geth/COPYING.LESSER
  • geth/Dockerfile
  • geth/Dockerfile.alltools
  • geth/Makefile
  • geth/README.md
  • geth/SECURITY.md
  • geth/accounts/abi/abi.go
  • geth/accounts/abi/abi_test.go
  • geth/accounts/abi/argument.go
  • geth/accounts/abi/bind/auth.go
  • geth/accounts/abi/bind/backend.go
  • geth/accounts/abi/bind/backends/simulated.go
  • geth/accounts/abi/bind/backends/simulated_test.go
  • geth/accounts/abi/bind/base.go
  • geth/accounts/abi/bind/base_test.go
  • geth/accounts/abi/bind/bind.go
  • geth/accounts/abi/bind/template.go
  • geth/accounts/abi/bind/util.go
  • geth/accounts/abi/bind/util_test.go
  • geth/accounts/abi/doc.go
  • geth/accounts/abi/error.go
  • geth/accounts/abi/error_handling.go
  • geth/accounts/abi/event.go
  • geth/accounts/abi/event_test.go
  • geth/accounts/abi/method.go
  • geth/accounts/abi/method_test.go
  • geth/accounts/abi/pack.go
  • geth/accounts/abi/pack_test.go
  • geth/accounts/abi/packing_test.go
  • geth/accounts/abi/reflect.go
  • geth/accounts/abi/reflect_test.go
  • geth/accounts/abi/selector_parser.go
  • geth/accounts/abi/selector_parser_test.go
  • geth/accounts/abi/topics.go
Files skipped from review due to trivial changes (7)
  • cmd/ethclient/const.go
  • geth/.gitattributes
  • geth/.github/ISSUE_TEMPLATE/feature.md
  • geth/.github/ISSUE_TEMPLATE/question.md
  • geth/.gitignore
  • geth/.mailmap
  • geth/.markdownlintignore
Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md
Additional Context Used
GitHub Check Runs (1)
lint failure (10)

eth/crypto/ethsecp256k1/ethsecp256k1.go: [failure] 12-12:
File is not goimports-ed with -local github.com/NibiruChain/nibiru (goimports)


eth/crypto/hd/benchmark_test.go: [failure] 6-6:
File is not goimports-ed with -local github.com/NibiruChain/nibiru (goimports)


eth/ethereum/eip712/encoding.go: [failure] 14-14:
File is not goimports-ed with -local github.com/NibiruChain/nibiru (goimports)


eth/ethereum/eip712/encoding_legacy.go: [failure] 14-14:
File is not goimports-ed with -local github.com/NibiruChain/nibiru (goimports)


eth/ethereum/eip712/preprocess.go: [failure] 7-7:
File is not goimports-ed with -local github.com/NibiruChain/nibiru (goimports)

Additional comments not posted (38)
geth/.dockerignore (1)

1-5: LGTM! These changes effectively exclude unnecessary files from the Docker build context, improving build performance and reducing the Docker image size.

geth/.gitmodules (1)

1-8: LGTM! The configuration of the submodules for tests and benchmarks is correct, and the use of shallow cloning is a good practice for optimizing clone operations.

eth/types/errors.go (1)

1-17: LGTM! The mechanism for registering module-specific errors is correctly implemented. Consider adding more module-specific errors as needed to cover the full scope of Ethereum functionalities being integrated.

geth/.markdownlint.yml (1)

1-21: LGTM! The markdownlint configuration is appropriately customized to fit the project's documentation style and requirements.

geth/.github/ISSUE_TEMPLATE/bug.md (1)

1-30: LGTM! The bug report template is well-structured and comprehensive. Consider using consistent spelling (either American or British English) throughout the project documentation to maintain consistency.

eth/crypto/codec/codec.go (1)

1-15: LGTM! The registration of Ethereum-specific cryptographic key types with the Cosmos SDK's interface registry is correctly implemented, enabling Ethereum compatibility.

eth/ethereum/eip712/domain.go (1)

1-20: LGTM! The creation of the EIP-712 domain is correctly implemented. Consider making the domain parameters configurable in the future to support multiple environments or chains.

geth/.github/no-response.yml (1)

1-11: LGTM! The configuration of the GitHub no-response bot is correctly set up, helping to maintain the cleanliness of the issue tracker by automatically closing inactive issues.

geth/.github/stale.yml (1)

1-17: LGTM! The stale bot configuration follows common practices and is correctly set up.

geth/.github/workflows/markdown-links.yml (1)

1-29: LGTM! The workflow for checking Markdown links is correctly set up and follows best practices for GitHub Actions.

geth/.github/workflows/dependencies.yml (1)

1-28: LGTM! The workflow for dependency review and vulnerability checks is correctly set up and follows best practices for GitHub Actions.

eth/types/codec.go (1)

1-26: LGTM! The interface registrations for Ethereum-specific types with the Cosmos SDK's codec are correctly implemented.

geth/.github/workflows/build.yml (1)

1-33: LGTM! The build workflow is correctly set up and follows best practices for GitHub Actions.

eth/crypto/codec/amino.go (1)

1-27: LGTM! The registration of Ethereum-specific cryptographic types with the Amino codec is correctly implemented.

geth/.github/workflows/test.yml (2)

13-15: Ensure that using the master branch for the rokroskar/workflow-run-cleanup-action is intentional. It's generally safer to use a specific version or tag to avoid unexpected changes.


22-35: The test job runs conditionally based on the presence of changes in Go files, go.mod, or go.sum. Verify that this condition aligns with the project's testing strategy, especially for changes that might not directly modify these files but still require testing.

eth/encoding/codec/codec.go (2)

14-19: LGTM! The function RegisterLegacyAminoCodec correctly registers codecs for various types and crypto functionalities. It follows best practices for codec registration in the Cosmos SDK.


21-26: LGTM! The function RegisterInterfaces properly registers interfaces for Ethereum-related types and crypto functionalities, ensuring compatibility with the Cosmos SDK's interface registry.

eth/types/hdpath.go (1)

20-33: The function NewHDPathIterator is well-implemented, providing a flexible way to create HD path iterators. Ensure that error handling is performed wherever this function is called, as it can return an error if the base path is invalid.

geth/.github/workflows/security.yml (1)

27-31: Ensure that using the master branch for the cosmos/gosec action is intentional. Similar to other GitHub Actions, it's generally safer to use a specific version or tag to avoid unexpected changes.

eth/types/safe_math.go (2)

15-21: The function SafeNewIntFromBigInt correctly checks for the 256-bit boundary before creating a new sdkmath.Int. This is a good practice for preventing integer overflow errors.


28-35: The function SafeInt64 properly checks for overflow when casting a uint64 to an int64. This is crucial for ensuring data integrity and preventing potential overflow errors.

eth/encoding/config_test.go (1)

17-41: The test TestTxEncoding is well-structured and covers the essential aspects of Ethereum transaction encoding. Ensure that additional test cases are added to cover edge cases and potential error conditions for a more comprehensive test coverage.

geth/.github/CODEOWNERS (1)

4-24: Verify that the CODEOWNERS file is up-to-date with the current project structure and team responsibilities. Ensure that all critical paths have designated code owners to streamline the review process and maintain code quality.

eth/encoding/config.go (1)

14-31: LGTM! The MakeConfig function is correctly implemented and follows best practices for creating an encoding configuration.

geth/.github/workflows/super-linter.yml (1)

1-38: LGTM! The GitHub Actions workflow for linting is correctly set up and follows best practices.

eth/types/assert.go (1)

12-43: LGTM! The utility functions for Ethereum address and hash validations are correctly implemented and follow best practices.

eth/types/chain_id.go (1)

13-55: LGTM! The regular expression and functions related to Ethereum chain ID validation and parsing are correctly implemented and follow best practices.

eth/crypto/keyring/options.go (1)

13-41: LGTM! The keyring options, including supported algorithms and the configuration for the Ethereum Secp256k1 curve, are correctly implemented and follow best practices.

eth/crypto/secp256r1/verify.go (1)

25-51: LGTM! The signature verification functionality using the Secp256r1 curve is correctly implemented and follows best practices.

eth/types/chain_id_test.go (1)

11-86: LGTM! The test cases for chain ID parsing and validation are comprehensive and correctly implemented.

eth/ethereum/eip712/eip712_legacy.go (2)

8-8: Consider removing the comment // #nosec G702 for sensitive import or provide a more detailed explanation.
While it's clear that this is meant to suppress a security linting rule, it's not immediately clear why this suppression is necessary or safe in this context. Providing more context or justification for security-related suppressions can help maintainers and reviewers understand the security posture of the code.


142-161: The function walkFields uses recursion to handle pointer and interface types, but it lacks documentation explaining its purpose and how it works. Given the complexity of reflection and the operations performed here, adding a comment explaining the rationale behind this function would improve code readability and maintainability.

eth/ethereum/eip712/types.go (1)

34-87: The function createEIP712Types iterates over message payloads to create EIP-712 types. Consider adding error handling for the messagePayload.numPayloadMsgs to ensure it does not lead to an out-of-bounds error in case of malformed input.

Additionally, the function could benefit from more detailed comments explaining the purpose of each step, especially since working with EIP-712 types involves complex data structures.

eth/ethereum/eip712/eip712_test.go (4)

116-388: The test function TestEIP712 is comprehensive, covering various scenarios for EIP-712 signature verification. However, it could benefit from the following improvements:

  1. Consider breaking down this large test function into smaller, more focused test functions. This would improve readability and make it easier to identify which specific scenarios are being tested.
  2. Add more detailed comments explaining the purpose and expected outcome of each test case. This would help future maintainers understand the intent behind each test.

390-424: The function verifyEIP712SignatureVerification performs signature verification for EIP-712 messages. It's well-implemented, but consider adding comments to explain the rationale behind each verification step, especially the sanity check with random bytes. This would enhance the readability and maintainability of the test code.


426-492: The function verifySignDocFlattening and related functions (verifyPayloadAgainstFlattened, verifyPayloadMapAgainstFlattenedMap) test the flattening algorithm for EIP-712 messages. These functions are critical for ensuring the correctness of the flattening logic. Consider the following improvements:

  1. Add more detailed comments explaining the purpose and logic of each function, especially given the complexity of the flattening algorithm.
  2. Consider adding more edge case tests to ensure the flattening algorithm behaves correctly in all scenarios.

494-511: The function verifyBasicTypedData tests the basic functionality of TypedData generation. It's important to ensure that the TypedData generated matches the expected structure. Consider adding assertions to verify other aspects of the typedData object, such as the Types and Domain fields, to ensure comprehensive coverage of the TypedData generation logic.

Comment on lines +17 to +34
func BenchmarkPubKey_VerifySignature(b *testing.B) {
privKey, err := GenerateKey()
if err != nil {
b.Fatal(err)
}
pubKey := privKey.PubKey()

b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
msg := []byte(fmt.Sprintf("%10d", i))
sig, err := privKey.Sign(msg)
if err != nil {
b.Fatal(err)
}
pubKey.VerifySignature(msg, sig)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider pre-generating the messages outside of the benchmark loop to reduce overhead not directly related to the signature verification process being benchmarked.

+   messages := make([][]byte, b.N)
+   for i := range messages {
+       messages[i] = []byte(fmt.Sprintf("%10d", i))
+   }
-       msg := []byte(fmt.Sprintf("%10d", i))
+       msg := messages[i]

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
func BenchmarkPubKey_VerifySignature(b *testing.B) {
privKey, err := GenerateKey()
if err != nil {
b.Fatal(err)
}
pubKey := privKey.PubKey()
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
msg := []byte(fmt.Sprintf("%10d", i))
sig, err := privKey.Sign(msg)
if err != nil {
b.Fatal(err)
}
pubKey.VerifySignature(msg, sig)
}
}
func BenchmarkPubKey_VerifySignature(b *testing.B) {
privKey, err := GenerateKey()
if err != nil {
b.Fatal(err)
}
pubKey := privKey.PubKey()
messages := make([][]byte, b.N)
for i := range messages {
messages[i] = []byte(fmt.Sprintf("%10d", i))
}
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
msg := messages[i]
sig, err := privKey.Sign(msg)
if err != nil {
b.Fatal(err)
}
pubKey.VerifySignature(msg, sig)
}
}

geth/.github/workflows/lint.yml Show resolved Hide resolved
Comment on lines +3 to +4
run:
timeout: 20m
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider increasing the timeout for golangci-lint to accommodate larger codebases or more complex analyses. A timeout of 20m might be too short for comprehensive linting in some scenarios.

-  timeout: 20m
+  timeout: 30m

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
run:
timeout: 20m
run:
timeout: 30m

eth/ethereum/eip712/preprocess.go Outdated Show resolved Hide resolved
eth/crypto/hd/benchmark_test.go Outdated Show resolved Hide resolved
geth/.github/CONTRIBUTING.md Show resolved Hide resolved
geth/.github/CONTRIBUTING.md Show resolved Hide resolved
Comment on lines +140 to +220
// recursivelyAddTypesToRoot walks all types in the given map
// and recursively adds sub-maps as new types when necessary.
// It adds all type definitions to typeMap, then returns a key
// to the json object's type definition within the map.
func recursivelyAddTypesToRoot(
typeMap apitypes.Types,
rootType string,
prefix string,
payload gjson.Result,
) (string, error) {
typesToAdd := []apitypes.Type{}

// Must sort the JSON keys for deterministic type generation.
sortedFieldNames, err := sortedJSONKeys(payload)
if err != nil {
return "", errorsmod.Wrap(err, "unable to sort object keys")
}

typeDef := typeDefForPrefix(prefix, rootType)

for _, fieldName := range sortedFieldNames {
field := payload.Get(fieldName)
if !field.Exists() {
continue
}

// Handle array type by unwrapping the first element.
// Note that arrays with multiple types are not supported
// using EIP-712, so we can ignore that case.
isCollection := false
if field.IsArray() {
fieldAsArray := field.Array()

if len(fieldAsArray) == 0 {
// Arbitrarily add string[] type to handle empty arrays,
// since we cannot access the underlying object.
emptyArrayType := "string[]"
typesToAdd = appendedTypesList(typesToAdd, fieldName, emptyArrayType)

continue
}

field = fieldAsArray[0]
isCollection = true
}

ethType := getEthTypeForJSON(field)

// Handle JSON primitive types by adding the corresponding
// EIP-712 type to the types schema.
if ethType != "" {
if isCollection {
ethType += "[]"
}
typesToAdd = appendedTypesList(typesToAdd, fieldName, ethType)

continue
}

// Handle object types recursively. Note that nested array types are not supported
// in EIP-712, so we can exclude that case.
if field.IsObject() {
fieldPrefix := prefixForSubField(prefix, fieldName)

fieldTypeDef, err := recursivelyAddTypesToRoot(typeMap, rootType, fieldPrefix, field)
if err != nil {
return "", err
}

fieldTypeDef = sanitizeTypedef(fieldTypeDef)
if isCollection {
fieldTypeDef += "[]"
}

typesToAdd = appendedTypesList(typesToAdd, fieldName, fieldTypeDef)

continue
}
}

return addTypesToRoot(typeMap, typeDef, typesToAdd)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function recursivelyAddTypesToRoot is complex and performs multiple operations, including handling of arrays, slices, and recursive type addition. Consider the following improvements:

  1. Break down this function into smaller, more focused functions to improve readability and maintainability.
  2. Add comments to explain the logic, especially for complex sections like handling of arrays and slices, and the recursive nature of the function.

Refactoring suggestion:

- // Current implementation
+ // Suggested refactoring into smaller functions with clear responsibilities

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// recursivelyAddTypesToRoot walks all types in the given map
// and recursively adds sub-maps as new types when necessary.
// It adds all type definitions to typeMap, then returns a key
// to the json object's type definition within the map.
func recursivelyAddTypesToRoot(
typeMap apitypes.Types,
rootType string,
prefix string,
payload gjson.Result,
) (string, error) {
typesToAdd := []apitypes.Type{}
// Must sort the JSON keys for deterministic type generation.
sortedFieldNames, err := sortedJSONKeys(payload)
if err != nil {
return "", errorsmod.Wrap(err, "unable to sort object keys")
}
typeDef := typeDefForPrefix(prefix, rootType)
for _, fieldName := range sortedFieldNames {
field := payload.Get(fieldName)
if !field.Exists() {
continue
}
// Handle array type by unwrapping the first element.
// Note that arrays with multiple types are not supported
// using EIP-712, so we can ignore that case.
isCollection := false
if field.IsArray() {
fieldAsArray := field.Array()
if len(fieldAsArray) == 0 {
// Arbitrarily add string[] type to handle empty arrays,
// since we cannot access the underlying object.
emptyArrayType := "string[]"
typesToAdd = appendedTypesList(typesToAdd, fieldName, emptyArrayType)
continue
}
field = fieldAsArray[0]
isCollection = true
}
ethType := getEthTypeForJSON(field)
// Handle JSON primitive types by adding the corresponding
// EIP-712 type to the types schema.
if ethType != "" {
if isCollection {
ethType += "[]"
}
typesToAdd = appendedTypesList(typesToAdd, fieldName, ethType)
continue
}
// Handle object types recursively. Note that nested array types are not supported
// in EIP-712, so we can exclude that case.
if field.IsObject() {
fieldPrefix := prefixForSubField(prefix, fieldName)
fieldTypeDef, err := recursivelyAddTypesToRoot(typeMap, rootType, fieldPrefix, field)
if err != nil {
return "", err
}
fieldTypeDef = sanitizeTypedef(fieldTypeDef)
if isCollection {
fieldTypeDef += "[]"
}
typesToAdd = appendedTypesList(typesToAdd, fieldName, fieldTypeDef)
continue
}
}
return addTypesToRoot(typeMap, typeDef, typesToAdd)

Comment on lines +14 to +18
messagePayload, err := createEIP712MessagePayload(data)
message := messagePayload.message
if err != nil {
return apitypes.TypedData{}, err
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider handling the error immediately after createEIP712MessagePayload to avoid accessing messagePayload.message when err is not nil.

- message := messagePayload.message
  if err != nil {
+   return apitypes.TypedData{}, err
  }
+ message := messagePayload.message

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
messagePayload, err := createEIP712MessagePayload(data)
message := messagePayload.message
if err != nil {
return apitypes.TypedData{}, err
}
messagePayload, err := createEIP712MessagePayload(data)
if err != nil {
return apitypes.TypedData{}, err
}
message := messagePayload.message

Comment on lines +120 to +123
// TODO: remove
if len(digestBz) != crypto.DigestLength {
digestBz = crypto.Keccak256Hash(digestBz).Bytes()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider removing the modification of the digest based on its length to ensure consistent behavior.

- // TODO: remove
- if len(digestBz) != crypto.DigestLength {
-     digestBz = crypto.Keccak256Hash(digestBz).Bytes()
- }

This modification could lead to unexpected behavior and should be avoided unless there's a specific reason for it. Ensure that the input to the Sign function is always the correct length.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// TODO: remove
if len(digestBz) != crypto.DigestLength {
digestBz = crypto.Keccak256Hash(digestBz).Bytes()
}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review Status

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between f7a9a66 and c2a3807.
Files selected for processing (8)
  • eth/crypto/ethsecp256k1/ethsecp256k1.go (1 hunks)
  • eth/crypto/hd/benchmark_test.go (1 hunks)
  • eth/ethereum/eip712/eip712_fuzzer_test.go (1 hunks)
  • eth/ethereum/eip712/eip712_test.go (1 hunks)
  • eth/ethereum/eip712/encoding.go (1 hunks)
  • eth/ethereum/eip712/encoding_legacy.go (1 hunks)
  • eth/ethereum/eip712/preprocess.go (1 hunks)
  • eth/ethereum/eip712/preprocess_test.go (1 hunks)
Files skipped from review as they are similar to previous changes (8)
  • eth/crypto/ethsecp256k1/ethsecp256k1.go
  • eth/crypto/hd/benchmark_test.go
  • eth/ethereum/eip712/eip712_fuzzer_test.go
  • eth/ethereum/eip712/eip712_test.go
  • eth/ethereum/eip712/encoding.go
  • eth/ethereum/eip712/encoding_legacy.go
  • eth/ethereum/eip712/preprocess.go
  • eth/ethereum/eip712/preprocess_test.go

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Comment on lines +57 to +100
// legacyDecodeAminoSignDoc attempts to decode the provided sign doc (bytes) as an Amino payload
// and returns a signable EIP-712 TypedData object.
func legacyDecodeAminoSignDoc(signDocBytes []byte) (apitypes.TypedData, error) {
// Ensure codecs have been initialized
if err := validateCodecInit(); err != nil {
return apitypes.TypedData{}, err
}

var aminoDoc legacytx.StdSignDoc
if err := aminoCodec.UnmarshalJSON(signDocBytes, &aminoDoc); err != nil {
return apitypes.TypedData{}, err
}

var fees legacytx.StdFee
if err := aminoCodec.UnmarshalJSON(aminoDoc.Fee, &fees); err != nil {
return apitypes.TypedData{}, err
}

// Validate payload messages
msgs := make([]sdk.Msg, len(aminoDoc.Msgs))
for i, jsonMsg := range aminoDoc.Msgs {
var m sdk.Msg
if err := aminoCodec.UnmarshalJSON(jsonMsg, &m); err != nil {
return apitypes.TypedData{}, fmt.Errorf("failed to unmarshal sign doc message: %w", err)
}
msgs[i] = m
}

if err := legacyValidatePayloadMessages(msgs); err != nil {
return apitypes.TypedData{}, err
}

// Use first message for fee payer and type inference
msg := msgs[0]

// By convention, the fee payer is the first address in the list of signers.
feePayer := msg.GetSigners()[0]
feeDelegation := &FeeDelegationOptions{
FeePayer: feePayer,
}

chainID, err := ethtypes.ParseChainID(aminoDoc.ChainID)
if err != nil {
return apitypes.TypedData{}, errors.New("invalid chain ID passed as argument")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider refining the error message for an invalid chain ID to include more context about the expected format or values.

- return apitypes.TypedData{}, errors.New("invalid chain ID passed as argument")
+ return apitypes.TypedData{}, fmt.Errorf("invalid chain ID '%s' passed as argument", aminoDoc.ChainID)

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// legacyDecodeAminoSignDoc attempts to decode the provided sign doc (bytes) as an Amino payload
// and returns a signable EIP-712 TypedData object.
func legacyDecodeAminoSignDoc(signDocBytes []byte) (apitypes.TypedData, error) {
// Ensure codecs have been initialized
if err := validateCodecInit(); err != nil {
return apitypes.TypedData{}, err
}
var aminoDoc legacytx.StdSignDoc
if err := aminoCodec.UnmarshalJSON(signDocBytes, &aminoDoc); err != nil {
return apitypes.TypedData{}, err
}
var fees legacytx.StdFee
if err := aminoCodec.UnmarshalJSON(aminoDoc.Fee, &fees); err != nil {
return apitypes.TypedData{}, err
}
// Validate payload messages
msgs := make([]sdk.Msg, len(aminoDoc.Msgs))
for i, jsonMsg := range aminoDoc.Msgs {
var m sdk.Msg
if err := aminoCodec.UnmarshalJSON(jsonMsg, &m); err != nil {
return apitypes.TypedData{}, fmt.Errorf("failed to unmarshal sign doc message: %w", err)
}
msgs[i] = m
}
if err := legacyValidatePayloadMessages(msgs); err != nil {
return apitypes.TypedData{}, err
}
// Use first message for fee payer and type inference
msg := msgs[0]
// By convention, the fee payer is the first address in the list of signers.
feePayer := msg.GetSigners()[0]
feeDelegation := &FeeDelegationOptions{
FeePayer: feePayer,
}
chainID, err := ethtypes.ParseChainID(aminoDoc.ChainID)
if err != nil {
return apitypes.TypedData{}, errors.New("invalid chain ID passed as argument")
return apitypes.TypedData{}, fmt.Errorf("invalid chain ID '%s' passed as argument", aminoDoc.ChainID)

Comment on lines +249 to +263
// getMsgType returns the message type prefix for the given Cosmos SDK Msg
func getMsgType(msg sdk.Msg) (string, error) {
jsonBytes, err := aminoCodec.MarshalJSON(msg)
if err != nil {
return "", err
}

var jsonMsg aminoMessage
if err := json.Unmarshal(jsonBytes, &jsonMsg); err != nil {
return "", err
}

// Verify Type was successfully filled in
if jsonMsg.Type == "" {
return "", errors.New("could not decode message: type is missing")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider refining the error message to include more context about the expected 'Type' field.

- return "", errors.New("could not decode message: type is missing")
+ return "", fmt.Errorf("could not decode message: 'Type' field is missing in JSON: %s", string(jsonBytes))

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// getMsgType returns the message type prefix for the given Cosmos SDK Msg
func getMsgType(msg sdk.Msg) (string, error) {
jsonBytes, err := aminoCodec.MarshalJSON(msg)
if err != nil {
return "", err
}
var jsonMsg aminoMessage
if err := json.Unmarshal(jsonBytes, &jsonMsg); err != nil {
return "", err
}
// Verify Type was successfully filled in
if jsonMsg.Type == "" {
return "", errors.New("could not decode message: type is missing")
// getMsgType returns the message type prefix for the given Cosmos SDK Msg
func getMsgType(msg sdk.Msg) (string, error) {
jsonBytes, err := aminoCodec.MarshalJSON(msg)
if err != nil {
return "", err
}
var jsonMsg aminoMessage
if err := json.Unmarshal(jsonBytes, &jsonMsg); err != nil {
return "", err
}
// Verify Type was successfully filled in
if jsonMsg.Type == "" {
return "", fmt.Errorf("could not decode message: 'Type' field is missing in JSON: %s", string(jsonBytes))

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Comment on lines +63 to +65
- [#1837](https://github.com/NibiruChain/nibiru/pull/1837) - feat(eth): protos, eth types, and evm module types
- [#1838](https://github.com/NibiruChain/nibiru/pull/1838) - feat(eth): Go-ethereum, crypto, encoding, and unit tests for evm/types
- [#1841](https://github.com/NibiruChain/nibiru/pull/1841) - feat(eth): Collections encoders for bytes, Ethereum addresses, and Ethereum hashes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure consistency in the formatting of changelog entries. Consider adding a period at the end of each entry to maintain uniformity.

- - [#1837](https://github.com/NibiruChain/nibiru/pull/1837) - feat(eth): protos, eth types, and evm module types
- - [#1838](https://github.com/NibiruChain/nibiru/pull/1838) - feat(eth): Go-ethereum, crypto, encoding, and unit tests for evm/types
- - [#1841](https://github.com/NibiruChain/nibiru/pull/1841) - feat(eth): Collections encoders for bytes, Ethereum addresses, and Ethereum hashes 
+ - [#1837](https://github.com/NibiruChain/nibiru/pull/1837) - feat(eth): Protos, eth types, and evm module types.
+ - [#1838](https://github.com/NibiruChain/nibiru/pull/1838) - feat(eth): Go-ethereum, crypto, encoding, and unit tests for evm/types.
+ - [#1841](https://github.com/NibiruChain/nibiru/pull/1841) - feat(eth): Collections encoders for bytes, Ethereum addresses, and Ethereum hashes.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
- [#1837](https://github.com/NibiruChain/nibiru/pull/1837) - feat(eth): protos, eth types, and evm module types
- [#1838](https://github.com/NibiruChain/nibiru/pull/1838) - feat(eth): Go-ethereum, crypto, encoding, and unit tests for evm/types
- [#1841](https://github.com/NibiruChain/nibiru/pull/1841) - feat(eth): Collections encoders for bytes, Ethereum addresses, and Ethereum hashes
- [#1837](https://github.com/NibiruChain/nibiru/pull/1837) - feat(eth): Protos, eth types, and evm module types.
- [#1838](https://github.com/NibiruChain/nibiru/pull/1838) - feat(eth): Go-ethereum, crypto, encoding, and unit tests for evm/types.
- [#1841](https://github.com/NibiruChain/nibiru/pull/1841) - feat(eth): Collections encoders for bytes, Ethereum addresses, and Ethereum hashes.

@Unique-Divine Unique-Divine merged commit 1a46a9b into main Apr 16, 2024
12 checks passed
@Unique-Divine Unique-Divine deleted the ud/evm branch April 16, 2024 08:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants